package Meter::Action::AddMetering;

#===============================================================================
#     REVISION:  $Id: AddMetering.pm 97 2011-07-19 14:11:46Z xdr.box@gmail.com $
#  DESCRIPTION:  Add a new metering item
#===============================================================================

use strict;
use warnings;

use Readonly;
Readonly our $VERSION => qw($Revision: 97 $) [1];

use English qw( -no_match_vars );

#use Smart::Comments;

use base qw(Meter::Action);

use Meter::Log;
use Meter::Meterings;

use Meter::Utils qw(
    inflate_iso8601_date
    get_most_recent_user_metering
);

sub generate_page_content {
    my $self = shift;

    my $logger     = get_logger();
    my $appartment = $self->{'user'}->appartment();

    if ( !$appartment ) {
        $logger->warn( 'User '
                . $self->{'user'}->username()
                . ' has not set appartment info yet' );

        return $self->redirect_error(
            'Необходимо вначале задать информацию по квартире и счётчикам',
            'appartment_info'
        );
    }

    if ( $ENV{'REQUEST_METHOD'} eq 'GET' ) {
        return $self->_prefill_form();
    }
    else {
        return $self->_add_metering();
    }
}

sub _prefill_form {
    my $self = shift;

    my $most_recent = get_most_recent_user_metering( $self->{'user'} );

    my $now = $self->now();

    if ($most_recent) {
        return $self->process_template(
            'add_metering.tt2',
            {   start_date => $most_recent->end_date->ymd(),
                end_date   => $now->ymd(),
                cold_water_start_amount =>
                    $most_recent->cold_water_end_amount(),
                cold_water_end_amount => q{?},
                hot_water_start_amount =>
                    $most_recent->hot_water_end_amount(),
                hot_water_end_amount => q{?},
            }
        );
    }
    else {
        return $self->process_template( 'add_metering.tt2',
            { end_date => $self->now()->ymd(), } );
    }
}

sub _add_metering {
    my $self = shift;

    my $logger = get_logger();

    my $appartment  = $self->{'user'}->appartment();
    my $most_recent = get_most_recent_user_metering( $self->{'user'} );

    my $now = $self->now();

    my $error_prefix
        = 'Ошибка добавления показаний счётчиков';
    my $start_date
        = eval { inflate_iso8601_date( $self->{'params'}{'start_date'} ) };

    if ($EVAL_ERROR) {
        my $why = $EVAL_ERROR;

        $logger->error("Cannot parse date: $why");

        return $self->redirect_error(
            "$error_prefix: дата начала периода не соответствует установленному формату",
            'add_metering'
        );
    }

    if ( $start_date > $now ) {
        return $self->redirect_error(
            "$error_prefix: нельзя добавлять показания будующим числом",
            'add_metering'
        );
    }

    if ($most_recent) {
        if ( $start_date < $most_recent->end_date() ) {
            return $self->redirect_error(
                "$error_prefix: новое показание перекрывается по дате с предыдущим",
                'add_metering'
            );
        }

        if ( $self->{'params'}{'cold_water_start_amount'}
            < $most_recent->cold_water_end_amount() )
        {
            return $self->redirect_error(
                "$error_prefix: новое начальное показание счётчика ХВ меньше чем конечное показание в прошлом периоде",
                'add_metering'
            );
        }

        if ( $self->{'params'}{'hot_water_start_amount'}
            < $most_recent->hot_water_end_amount() )
        {
            return $self->redirect_error(
                "$error_prefix: новое начальное показание счётчика ГВ меньше чем конечное показание в прошлом периоде",
                'add_metering'
            );
        }
    }

    my $metering = eval {
        Meter::Meterings->insert(
            {   appartment => $appartment,
                start_date => $self->{'params'}{'start_date'},
                end_date   => $self->{'params'}{'end_date'},
                cold_water_start_amount =>
                    $self->{'params'}{'cold_water_start_amount'},
                cold_water_end_amount =>
                    $self->{'params'}{'cold_water_end_amount'},
                hot_water_start_amount =>
                    $self->{'params'}{'hot_water_start_amount'},
                hot_water_end_amount =>
                    $self->{'params'}{'hot_water_end_amount'},
            }
        );
    };

    if ($EVAL_ERROR) {
        my $why = $EVAL_ERROR;

        $logger->error("Cannot add new metering: $why");

        return $self->redirect_error( $error_prefix, 'add_metering', $why );
    }

    $logger->info('New metering has been successfully added');

    return $self->redirect_ok(
        'Информация успешно добавлена',
        'show_meterings' );
}

sub get_error_regexes_list {
    my $self = shift;

    ## no critic (ProhibitComplexRegexes)
    return [
        {   regex =>
                qr/\Qend_date fails 'end_date > start_date' constraint\E/xms,
            message =>
                'дата конца периода должна быть больше даты начала',
        },

        {   regex =>
                qr/\Qcold_water_end_amount fails 'end_amount >= start_amount' constraint\E/xms,
            message =>
                'новое показание счётчика ХВ не может быть меньше предыдущего',
        },

        {   regex =>
                qr/\Qhot_water_end_amount fails 'end_amount >= start_amount' constraint\E/xms,
            message =>
                'новое показание счётчика ГВ не может быть меньше предыдущего',
        },

        {   regex => qr/\Qstart_date Invalid date format\E/xms,
            message =>
                'дата начала периода не соответствует установленному формату',
        },

        {   regex => qr/\Qend_date Invalid date format\E/xms,
            message =>
                'дата конца периода не соответствует установленному формату',
        },
    ];
}

1;
